use std::{
    collections::HashMap,
    sync::{Arc, Weak},
    time::Duration,
};

use rusb::{Context, DeviceHandle};
use ylong_runtime::sync::{
    mpsc::{bounded_channel, BoundedReceiver, BoundedSender},
    Mutex,
};

use crate::{
    common::task_message::TaskMessage,
    server::stub::Stub,
};

#[derive(Debug)]
pub struct Endpoint {
    pub config: u8,
    pub iface: u8,
    pub setting: u8,
    pub address: u8,
}

pub struct UsbStub {
    /// USB操作句柄
    // handle: DeviceHandle<Context>,
    rd_channel: Arc<Mutex<BoundedReceiver<TaskMessage>>>,
    /// 和rd_channel是一对channel， 在get_channel将该句柄的副本传递给stub,stub通过该句柄发送要写入usb的数据
    wr_channel: BoundedSender<TaskMessage>,
    /// 记录从channel的映射关系，从usb读到的数据通过映射进行分发
    channel_map: Arc<Mutex<HashMap<u128, BoundedSender<TaskMessage>>>>,
}

impl UsbStub {
    pub fn new() -> Self {
        let (wr_channel, rd_channel) = bounded_channel::<TaskMessage>(16);
        let channel_map = Arc::new(Mutex::new(HashMap::new()));
        let rd_channel = Arc::new(Mutex::new(rd_channel));

        Self { rd_channel, wr_channel, channel_map }
    }

    pub async fn get_session(&mut self) -> Stub {
        let mut map = self.channel_map.lock().await;
        let (wr, rd) = bounded_channel::<TaskMessage>(16);
        // let channel_id = rand::random(); // todo 动态生成
        let channel_id = 0;
        map.insert(channel_id, wr);
        Stub::new(self.wr_channel.clone(), rd)
    }

    #[allow(unused)]
    pub async fn close_session(&mut self) {
        // if let Some(rd) = &mut self.rd_channel {
        //         rd.close();
        //         self.rd_channel = None;
        // }
    }

    pub fn start_relay(&self, handle: DeviceHandle<Context>, _endpoint_in: Endpoint, endpoint_out: Endpoint) {
        let _channel_map_weak: Weak<Mutex<HashMap<u128, BoundedSender<TaskMessage>>>> =
            Arc::downgrade(&self.channel_map);
        let rd_channel_weak = Arc::downgrade(&self.rd_channel);

        ylong_runtime::spawn(async move {
            // 配置usb
            let _ = handle.set_active_configuration(endpoint_out.config);
            let _ = handle.claim_interface(endpoint_out.iface);
            let _ = handle.set_alternate_setting(endpoint_out.iface, endpoint_out.setting);

            loop {
                match rd_channel_weak.upgrade() {
                    Some(rd_channel) => {
                        let mut rd_channel = rd_channel.lock().await;
                        ylong_runtime::select! {
                            // 接收来自stub的数据，转发给USB
                            msg = rd_channel.recv_timeout(Duration::from_secs(60 * 5)) => {
                                match msg {
                                    Ok(msg) => {
                                        // log::info!("recv msg {msg:?}");

                                        //写入usb
                                        let buff = msg.to_vec();
                                        match handle.write_bulk(endpoint_out.address, &buff, Duration::from_secs(50)) {
                                            Ok(n) => {
                                                // log::info!("write_bulk {n}");
                                                if n != buff.len() {
                                                    log::error!("write_bulk len failed. Expected to write {}, actually wrote {n}", buff.len());
                                                    break;
                                                }
                                            },
                                            Err(err) => {
                                                log::error!("write_bulk failed, {:?}", err);
                                                break;
                                            },
                                        };

                                        // 测试，转发给原通道， 实际应该写usb
                                        // if !UsbStub::senf_msg_to_porxy(&channel_map_weak, msg).await {
                                        //     break;
                                        // }
                                    },
                                    Err(err) => {
                                        log::error!("{err}");
                                        break;
                                    }
                                }
                            }
                            // 从usb读取数据
                            // msg = self.handle.read_frame() => {
                            //     // 将msg转换成TaskMessage
                            //     // 查询通道进行转发
                            // }
                            // msg = UsbStub::read_bulk(&handle, &endpoint_in) {

                            // }
                        }
                    }
                    None => {
                        log::warn!("session is close. break");
                        break;
                    }
                };
            }
            // todo 需要在这里关闭session, 回复usb的配置
        });
    }

    #[allow(unused)]
    async fn senf_msg_to_porxy(
        channel_map_weak: &Weak<Mutex<HashMap<u128, BoundedSender<TaskMessage>>>>, msg: TaskMessage,
    ) -> bool {
        match channel_map_weak.upgrade() {
            Some(channel_map) => {
                let map = channel_map.lock().await;
                match map.get(&msg.channel_id) {
                    Some(wr) => {
                        log::info!("send data");
                        let _ = wr.send(msg).await;
                        true
                    }
                    None => {
                        log::error!("nor found channel");
                        false
                    }
                }
            }
            None => {
                log::warn!("session is close. break");
                false
            }
        }
    }

    // pub fn write_bulk(handle: &DeviceHandle<Context>, endpoint_out: &Endpoint, msg: TaskMessage) -> bool {
    //     let buff = msg.to_vec();
    //     match handle.write_bulk(endpoint_out.address, &buff, Duration::from_secs(1)) {
    //         Ok(n) if n == buff.len() => true,
    //         Ok(n) => {
    //             log::error!("write_bulk failed, send len {} != {}", n, buff.len());
    //             false
    //         }
    //         Err(err) => {
    //             log::error!("write_bulk failed, {:?}", err);
    //             false
    //         }
    //     }
    // }

    // async fn read_bulk(handle: &DeviceHandle<Context>, endpoint_in: &Endpoint) -> Result<TaskMessage, HdcError> {
    //     ylong_runtime::spawn_blocking(move ||{
    //         let mut buff = Vec::with_capacity(255);
    //         buff.resize(255,0_u8);
    //         match handle.read_bulk(endpoint_in.address, &mut buff, Duration::from_secs(1)) {
    //             Ok(0) => {
    //                 let msg = "recv len 0, is close".to_owned();
    //                 log::error!("{msg}");
    //                 Err(HdcError::new(HdcErrorKind::HdcClose, msg))
    //             }
    //             Ok(n) => {
    //                 log::info!("read size {}", n);
    //                 buff.resize(n, 0);
    //                 buff.truncate(n);
    //                 let msg = TaskMessage::from_be_bytes(&buff)?;
    //                 Ok(msg)
    //             },
    //             Err(_) => {
    //                 let msg = "read filed.".to_owned();
    //                 log::error!("{msg}");
    //                 Err(HdcError::new(HdcErrorKind::HdcConnectionReset, msg))
    //             },
    //         }
    //     }).await;

    //     Ok(())
    // }

}

impl Drop for UsbStub {
    fn drop(&mut self) {
        log::warn!("UsbStub dorp");
    }
}
